package org.feidao.code4.handler;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.feidao.code4.codec.util.MBAPHeaderDecoder;
import org.feidao.code4.dataProcessor.RecMessageStrategy;
import org.feidao.code4.dataProcessor.RecMessageStrategyManager;
import org.feidao.code4.message.*;
import org.feidao.code4.netty.ChannelManager;

/**
 * Created with IntelliJ IDEA.
 * User: linghufeixia
 * Date: 2022-12-1
 * Description: request
 */
@Slf4j
public class TCPModbusResHandler extends SimpleChannelInboundHandler<TCPModbusByteBufHolder> {
    public static final int HEADER_LENGTH = 8;// // transactionId(2) + protocolId(2) + length(2) + unitId(1)+ functionCode(1)

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("channelActive");
        Channel channel = ctx.channel();
        log.info("channelActive channelId:" + channel.id().asLongText());
        log.info("channelActive 终端:" + channel.remoteAddress());
        ChannelManager.addChannel(channel.remoteAddress().toString(), channel);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("channelInactive");
        Channel channel = ctx.channel();
        ChannelManager.removeChannel(channel.remoteAddress().toString());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TCPModbusByteBufHolder modbusByteBufHolder) {
        log.info("channelRead0");
        int totalLen = modbusByteBufHolder.content().readableBytes();
        log.info("channelRead0:" + totalLen);
        if (totalLen < HEADER_LENGTH) {
            log.info("not modbus TCP protocol:");
            return;
        }
        //header
        MBAPHeader mbapHeader = MBAPHeaderDecoder.decode(modbusByteBufHolder.content());
        log.info("mbapHeader:" + mbapHeader.toString());
        //pdu
        PduPayload pduPayload = new PduPayload();
        short functionCode = modbusByteBufHolder.content().readUnsignedByte();
        pduPayload.setFunctionCode(functionCode);
        log.info("functionCode:" + functionCode);
        int dataLength = 0;
        if (totalLen > HEADER_LENGTH) {
            dataLength = totalLen - HEADER_LENGTH;
        }
        pduPayload.setDataLength((short) dataLength);
        log.info("dataLength:" + dataLength);
        byte[] data = new byte[dataLength];
        modbusByteBufHolder.content().readBytes(data);
        pduPayload.setData(data);

        RecMessageStrategy messageStrategy = RecMessageStrategyManager.getMessageStrategy(functionCode);
        if (messageStrategy != null) {
            messageStrategy.recMessage(channelHandlerContext.channel(), mbapHeader, pduPayload);
        } else {
            log.info("not support function code...");
        }

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        log.info("channelReadComplete");
        ctx.flush();
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        log.info("handlerRemoved");
        ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info("exceptionCaught");
        Channel channel = ctx.channel();
        ChannelManager.removeChannel(channel.remoteAddress().toString());
        cause.printStackTrace();
    }
}
